Java中的纳秒

您所在的位置:网站首页 jdk8 instant Java中的纳秒

Java中的纳秒

2023-12-31 07:26| 来源: 网络整理| 查看: 265

Java中的纳秒 前言JDK8获取纳秒的问题JDK9之后获取纳秒的问题参考资料

前言

最近在使用InfluxDB保存系统的操作日志,如果在插入的时候不指定time字段,influxDB会默认设置time,但一般来说,数据经过多方周转如果采用默认的插入时间,对业务来说误差较高。我们的日志是发送给kafka,然后消费者订阅kafka消费数据再保存到influxDB,数据会有延迟。因此会在数据产生的时候写入time字段值,对时间的精度要求比较高,这样才能有效防止数据丢失。 Java中时间精度最高的应该是纳秒了,所以查询了下获取纳秒的一些方法。

JDK8获取纳秒的问题

JDK8中提供了丰富的时间的工具类,但是实际上JDK8中没有真正获取纳秒的方法,可查看这篇文章,https://stackoverflow.com/questions/1712205/current-time-in-microseconds-in-java, Instant类中可以获取纳秒的方法,本质上是获取的毫秒,后6位都是0。

Instant instant = Instant.now(); int tt = instant.getNano(); System.out.println(tt); //返回的时间为576000000,后6位都是0>

查看java.time.Clock类的源码可发现,本质是获取当前的System.currentTimeMillis()生成时间类的。

static final class SystemClock extends Clock implements Serializable { private static final long serialVersionUID = 6740630888130243051L; private final ZoneId zone; SystemClock(ZoneId zone) { this.zone = zone; } @Override public ZoneId getZone() { return zone; } @Override public Clock withZone(ZoneId zone) { if (zone.equals(this.zone)) { // intentional NPE return this; } return new SystemClock(zone); } @Override public long millis() { return System.currentTimeMillis(); } @Override public Instant instant() { return Instant.ofEpochMilli(millis());//本质是获取当前的毫秒时间戳生成时间类的 } @Override public boolean equals(Object obj) { if (obj instanceof SystemClock) { return zone.equals(((SystemClock) obj).zone); } return false; } @Override public int hashCode() { return zone.hashCode() + 1; } @Override public String toString() { return "SystemClock[" + zone + "]"; } }

Jdk还有一个方法System.nanoTime()可以提供纳秒的精度测量的方法,一般可以用来计算2个方法之间的差值,不能直接转成时间戳。

long startTime = System.nanoTime(); // ... the code being measured ... long elapsedNanos = System.nanoTime() - startTime; //To compare elapsed time against a timeout, use

可以利用这个特性,初始化t1,获取差值从而获取纳秒。

t1=System.nanoTime(), offset=System.currentTimeMillis()*1_000_000 - t1, //获取当前的纳秒 currentNano=System.nanoTime() + offset

https://github.com/jenetics/jenetics/blob/master/jenetics/src/main/java/io/jenetics/util/NanoClock.java 就是利用这个方法实现的。

JDK9之后获取纳秒的问题

之前有提过这方面的缺陷,https://bugs.openjdk.java.net/browse/JDK-8068730,JDK9之后优化了获取纳秒的问题。

Instant instant = Instant.now(); int tt = instant.getNano(); System.out.println(tt); //返回的时间为72765400,已经包含了纳秒。

java.time.Clock源码里,增加了VM.getNanoTimeAdjustment方法获取纳秒。

public Instant instant() { // Take a local copy of offset. offset can be updated concurrently // by other threads (even if we haven't made it volatile) so we will // work with a local copy. long localOffset = offset; long adjustment = VM.getNanoTimeAdjustment(localOffset); if (adjustment == -1) { // -1 is a sentinel value returned by VM.getNanoTimeAdjustment // when the offset it is given is too far off the current UTC // time. In principle, this should not happen unless the // JVM has run for more than ~136 years (not likely) or // someone is fiddling with the system time, or the offset is // by chance at 1ns in the future (very unlikely). // We can easily recover from all these conditions by bringing // back the offset in range and retry. // bring back the offset in range. We use -1024 to make // it more unlikely to hit the 1ns in the future condition. localOffset = System.currentTimeMillis()/1000 - 1024; // retry adjustment = VM.getNanoTimeAdjustment(localOffset); if (adjustment == -1) { // Should not happen: we just recomputed a new offset. // It should have fixed the issue. throw new InternalError("Offset " + localOffset + " is not in range"); } else { // OK - recovery succeeded. Update the offset for the // next call... offset = localOffset; } } return Instant.ofEpochSecond(localOffset, adjustment); }

这时候如要获取纳秒的时间戳就简单了。

Instant instant = Instant.now(); int tt = instant.getNano(); // Represent a moment in UTC. long time = instant.toEpochMilli()/1000*1000_000_000 + tt; System.out.println(time); 参考资料 https://stackoverflow.com/questions/1712205/current-time-in-microseconds-in-javahttps://bugs.openjdk.java.net/browse/JDK-8068730https://github.com/jenetics/jenetics/blob/master/jenetics/src/main/java/io/jenetics/util/NanoClock.java


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3